package classfile

var (
	_attrDeprecated = &DeprecatedAttribute{}
	_attrSynthetic  = &SyntheticAttribute{}
)

type AttributeInfo interface {
	readInfo(reader *ClassReader)
}

// 读取属性表
func readAttributes(reader *ClassReader, cp ConstantPool) []AttributeInfo {
	var attributesCount = reader.readUint16()
	var attributes = make([]AttributeInfo, attributesCount)
	for i := range attributes {
		attributes[i] = readAttribute(reader, cp)
	}
	return attributes
}

// 读取单个属性
func readAttribute(reader *ClassReader, cp ConstantPool) AttributeInfo {
	var attrNameIndex = reader.readUint16()
	var attrName = cp.getUtf8(attrNameIndex)
	var attrLen = reader.readUint32()
	var attrInfo = newAttributeInfo(attrName, attrLen, cp)
	attrInfo.readInfo(reader)
	return attrInfo
}

// 根据名称来生成不同的属性
func newAttributeInfo(name string, length uint32, cp ConstantPool) AttributeInfo {
	switch name {
	// case "AnnotationDefault":
	case "BootstrapMethods":
		return &BootstrapMethodsAttribute{}
	case "Code":
		return &CodeAttribute{cp: cp}
	case "ConstantValue":
		return &ConstantValueAttribute{}
	case "Deprecated":
		return _attrDeprecated
	case "EnclosingMethod":
		return &EnclosingMethodAttribute{cp: cp}
	case "Exceptions":
		return &ExceptionsAttribute{}
	case "InnerClasses":
		return &InnerClassesAttribute{}
	case "LineNumberTable":
		return &LineNumberTableAttribute{}
	case "LocalVariableTable":
		return &LocalVariableTableAttribute{}
	case "LocalVariableTypeTable":
		return &LocalVariableTypeTableAttribute{}
		// case "MethodParameters":
		// case "RuntimeInvisibleAnnotations":
		// case "RuntimeInvisibleParameterAnnotations":
		// case "RuntimeInvisibleTypeAnnotations":
		// case "RuntimeVisibleAnnotations":
		// case "RuntimeVisibleParameterAnnotations":
		// case "RuntimeVisibleTypeAnnotations":
	case "Signature":
		return &SignatureAttribute{cp: cp}
	case "SourceFile":
		return &SourceFileAttribute{cp: cp}
		// case "SourceDebugExtension":
		// case "StackMapTable":
	case "Synthetic":
		return _attrSynthetic
	default:
		return &UnparsedAttribute{name, length, nil}
	}
}
